//
// Created by meow star on 2019/9/25.
//

#ifndef RCMD_RECALL_RECALL_MANAGER_H
#define RCMD_RECALL_RECALL_MANAGER_H

#include <define.h>
#include <recall_types.h>
#include <word2vec.h>
#include <string>
#include <vector>
#include <unordered_map>
#include "invert_index.cxx"
#include "recall_profile.h"
#include <map>
using namespace std;
struct RecallStrategyCell{
    string key;
    vector<string> source_limit;
    vector<string> limit_keys;
    int count;
};

struct RecallStrategy{
    map<string, vector<RecallStrategyCell>> recalls;
};

struct IIndexRecallResult{
    const ElemInfo* elem;
    float weight;
    string recall_key;
};

struct RecallResult{
    unordered_map<string, vector<IIndexRecallResult>> results;
};

class RecallManager{
public:
    RecallManager(WordVectorLib* w2v,string forward_index_path, map<string, string> iindex_pathes, int reload_delay = 0){
        _forward_index_path = forward_index_path;

        _fi = new ForwardIndex(_forward_index_path);
        _w2v = w2v;
        _reload_delay = reload_delay;

        for(auto it = iindex_pathes.begin(); it != iindex_pathes.end(); ++ it){
            InvertIndexSet<EzElem>* invert_index = new InvertIndexSet<EzElem>(_fi, it->first, it->second);
            size_t end_of_iindex_name = it->first.find("_");
            if (end_of_iindex_name == it->first.npos){
                spdlog::info("invalid iindex name, should end with _iindex, name={}", it->first);
                exit(-1);
            }
            _mp_key_2_iindex[it->first.substr(0, end_of_iindex_name)] = invert_index;
        }
    }
    int init();
    int reload_repository();
    int recall(RecallProfile* profile, RecallStrategy strategy, RecallResult& results);
    int stat_keywords(unordered_map<string, int>& keywords);
    int get_repository_status(json& result);
public:
    map<string, InvertIndexSet<EzElem>*> _mp_key_2_iindex;
    ForwardIndex* _fi;
    WordVectorLib* _w2v;
    string _forward_index_path;
    int _reload_delay;
};
#endif //RCMD_RECALL_RECALL_MANAGER_H
